/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ucmconfchecker.conformance;

import edu.uci.ics.jung.graph.DirectedSparseGraph;
import java.util.*;

/**
 *
 * @author Administrador
 */
public class Scenario<V/*vertex*/> extends DirectedSparseGraph<V,Edge>{
    
    private String name;
    public enum MultiType{
        AND, OR;
    }
    public static MultiType MULTITYPE_DEFAULT = MultiType.AND;
    
    private Map<V,MultiType> precondition = new HashMap<V,MultiType>();
    private Map<V,MultiType> postcondition = new HashMap<V,MultiType>();
    
    public Scenario(String name){
        this.name = name;
//        implementation = new DefaultDirectedGraph(new Edge().getClass());
    }
    @Override
    public boolean addVertex(V vertex){
        return super.addVertex(vertex);
    }
    
    public Collection<V> getVertexSet(){
        return super.getVertices();
    }
    public void addEdge(V source, V target){
        System.out.println("Edge:"+source+"->"+target);
        super.addEdge(new Edge(),source,target);
    }
    public Collection<Edge> getEdgeSet(){
        return super.getEdges();
    }
    @Override
    public V getSource(Edge edge){
        return (V)super.getSource(edge);
    }
    public V getTarget(Edge edge){
        return (V)super.getDest(edge);
    }
    
    public MultiType getPreconditionsType(V vertex){
        MultiType type = precondition.get(vertex);
        if(type==null)
            type = MULTITYPE_DEFAULT;
        return type;
    }
     public void settPreconditionsType(V vertex,MultiType type){
        precondition.put(vertex,type);
        
    }
    public MultiType getPosconditionsType(V vertex){
        MultiType type = postcondition.get(vertex);
        if(type==null)
            type = MULTITYPE_DEFAULT;
        return type;
    }
    public void setPostconditionsType(V vertex,MultiType type){
        postcondition.put(vertex,type);
        
    }
    public Set<V> getPreconditions(V vertex){
        Collection<Edge> in = super.getIncidentEdges(vertex);
        
        if(in!=null && !in.isEmpty()){
            Set<V> result = new HashSet<V>();
            for(Edge edge: in){
                if(!this.getSource(edge).equals(vertex))
                result.add(this.getSource(edge));
            }
            return result;
        }else{
            return null;
        }
    }
    public Set<V> getPostconditions(V vertex){
        Collection<Edge> out = super.getOutEdges(vertex);
        
        if(out!=null && !out.isEmpty()){
            Set<V> result = new HashSet<V>();
            for(Edge edge: out){
                result.add(this.getTarget(edge));
            }
            return result;
        }else{
            return null;
        }
    }

    public String getName() {
        return name;
    }   
    
    public String toString(){
        return name;
    }
    
    public Map<V, Integer> getIndexes() {
        Map<V, Integer> index= new HashMap<V, Integer>();
        boolean finish = false;
        while(!finish){
            finish = true;
            for(V vertex: this.getVertices()){
                if(!index.containsKey(vertex)){
                    index.put(vertex, 1);
                    finish=false;
                }else{
                    for(V predecesor: this.getPreconditions(vertex)){
                        if(index.containsKey(predecesor)){
                            if(index.get(predecesor)+1>index.get(vertex)){
                               index.put(vertex, index.get(predecesor)+1);
                               finish = false;
                            }
                        }else{
                            finish= false;
                        }
                    }
                }
            }
        }
        return index;
    }
    public Map<V, Integer> getIndexes(EventTrace<V> trace) {
        Map<V, Integer> index= getIndexes();
        List<Event<V>> eventList = new ArrayList<Event<V>>();
        eventList.addAll(trace);
        Collections.sort(eventList);

        Event<V> last=null;
//        int offset =1;
        for(Event<V> event: eventList){
            if(last!=null){
                if (this.containsVertex(event.getEvent())&& event.compareTo(last)>0){
//                    offset++;
                    Integer currentIndex = index.get(event.getEvent());
                    for(V other: index.keySet()){
                        Integer otherIndex = index.get(other);
                        if(currentIndex<otherIndex){
                            index.put(other, otherIndex+1);
                        }
                    }
                }
            }
//            index.put(event.getEvent(),column);
            last=event;
        }
        return index;
    }
}
